class_name UnitCombiner
extends Node

# ===============================================

@export var buffer_timer: Timer
@export var sfx: AudioStream

# ===============================================

var queued_updates := 0
var tween: Tween

# ===============================================

func queue_unit_combination_update() -> void:
	buffer_timer.start()

# ===============================================

# 将符合等级要求的所有单位按类别划分
func __group_units_in_tier_by_name(tier: int) -> Dictionary:
	var unit_groups: Dictionary = {}
	var units: Array = get_tree().get_nodes_in_group("units").filter(
		func(unit: Unit):
			return unit.stats.tier == tier
	)
	for unit: Unit in units:
		if unit_groups.has(unit.stats.name):
			unit_groups[unit.stats.name].append(unit)
		else:
			unit_groups[unit.stats.name] = [unit]
	return unit_groups


# 将各类单位按升级条件绑定成对
func __get_tuples_for_groups(groups: Dictionary) -> Array[Array]:
	var upgrades: Array[Array] = []
	for unit_name: String in groups:
		var units: Array = groups[unit_name]
		var i: int = 0
		while i <= units.size() - UnitStats.COMBINED_UNIT_REQUIREMENT:
			upgrades.append(units.slice(i, i + UnitStats.COMBINED_UNIT_REQUIREMENT))
			i += UnitStats.COMBINED_UNIT_REQUIREMENT
	return upgrades


# 将绑定的单位对合并成高级单位
func __combine_units(units: Array) -> void:
	units[0].stats.tier += 1
	for i: int in range(1, units.size()):
		units[i].remove_from_group("units")
		units[i].animation.play_combine_animation(units[0].global_position + Arena.QUARTER_CELL_SIZE)
	SFXPlayer.play(sfx)


func __update_unit_combinations(tier: int) -> void:
	var tuples: Array[Array] = __get_tuples_for_groups(__group_units_in_tier_by_name(tier))
	if tuples.is_empty():
		__on_units_combined(tier)
		return
	tween = create_tween()
	
	for combination:Array in tuples:
		tween.tween_callback(__combine_units.bind(combination))
		tween.tween_interval(UnitAnimation.COMBINE_ANIM_ELAPSED)
	tween.finished.connect(__on_units_combined.bind(tier), CONNECT_ONE_SHOT)


func __on_units_combined(tier: int) -> void:
	if tier == 1:
		__update_unit_combinations(2)
	else:
		queued_updates -= 1
		if queued_updates >= 1:
			__update_unit_combinations(1)


func __on_buffer_timer_timeout() -> void:
	queued_updates += 1
	if not tween or not tween.is_running():
		__update_unit_combinations(1)

# ===============================================

func _ready() -> void:
	buffer_timer.timeout.connect(__on_buffer_timer_timeout)
